package cloudspace.vm.javassist;

import java.util.List;

import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.expr.Expr;
import javassist.expr.Handler;

import org.apache.log4j.Logger;

import cloudspace.vm.javassist.AbstractCommand.CommandNotImplementedException;
import cloudspace.vm.javassist.AbstractCommand.SignatureType;


/**
 * The Class InsertBefore. This class is used to represent an insert before
 * command. It is used to limit the types of expressions and methods that can be
 * translated.
 * 
 * translate InsertBefore <Class Name> <Method name> <Source body>
 * 
 */
public class InsertBefore implements CommandInterface
{
    private Logger logger = Logger.getLogger( InsertBefore.class );

    private List<String> configArgs;


    /**
     * Instantiates a new insert before command.
     * 
     * @param args
     *            the args
     * 
     * @throws MalformedCommandException
     *             the malformed command exception
     */
    public InsertBefore( List<String> args ) throws MalformedCommandException
    {
        configArgs = args;
    }


    public void translate( Expr call, boolean isSuper )
        throws MalformedCommandException,
        CannotCompileException
    {
        if ( call instanceof Handler )
        {
            translate( (Handler)call );
            return;
        }
        throw new MalformedCommandException( "This command is not implemented for the parameters passed" );

    }


    /*
     * (non-Javadoc)
     * 
     * @see cloudspace.vm.javassist.commands.CommandInterface#translate
     * (javassist.CtMethod, java.lang.String)
     */
    public void translate( CtMethod member, String expressionName )
        throws MalformedCommandException,
        CannotCompileException,
        CommandNotImplementedException
    {
        throw new MalformedCommandException( "This command is not implemented for the parameters passed" );
    }


    /**
     * Translate.
     * 
     * @param call
     *            the call
     * 
     * @throws MalformedCommandException
     *             the malformed command exception
     * @throws CannotCompileException
     *             the cannot compile exception
     */
    public void translate( Handler call )
        throws MalformedCommandException,
        CannotCompileException
    {
        call.insertBefore( getReplacement() );
    }


    public String getReplacement()
    {

        return configArgs.get( 3 ).substring( 1,
            configArgs.get( 3 ).length() - 1 );
    }


    public String getSignature()
    {
        return configArgs.get( 1 );
    }


    public SignatureType getSignatureType()
    {
        return SignatureType.STATICDEFINITION;
    }


    public void translate( CtClass clazz )
        throws MalformedCommandException,
        CannotCompileException
    {
        CtClass superClazz;
        try
        {
            CtMethod[] meths = clazz.getDeclaredMethods();
            superClazz = clazz.getSuperclass();

            while ( superClazz != null )
            {
                if ( superClazz.getName().equals( getSignature() ) )
                {
                    for ( CtMethod meth : meths )
                    {
                        if ( meth.getName().endsWith( configArgs.get( 2 ) ) )
                            meth.insertBefore( getReplacement() );
                    }
                }
                superClazz = superClazz.getSuperclass();
            }
        }
        catch ( NotFoundException e )
        {
            logger.error( "Method to translate not found", e );
            ;
        }

    }

}
